home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume10 / xt-examples / part05 < prev    next >
Encoding:
Internet Message Format  |  1990-11-04  |  68.5 KB

  1. Path: uunet!timbuk!cs.umn.edu!uc!tut.cis.ohio-state.edu!cs.utexas.edu!sun-barr!newstop!sun!adobe.com!asente
  2. From: asente@adobe.com
  3. Newsgroups: comp.sources.x
  4. Subject: v10i045: Examples from New Xt Book, Part05/05
  5. Message-ID: <144425@sun.Eng.Sun.COM>
  6. Date: 1 Nov 90 05:52:34 GMT
  7. References: <csx-10i041:xt-examples@uunet.UU.NET>
  8. Sender: news@sun.Eng.Sun.COM
  9. Lines: 2190
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: asente@adobe.com
  13. Posting-number: Volume 10, Issue 45
  14. Archive-name: xt-examples/part05
  15.  
  16.  
  17. #! /bin/sh
  18. # This is a shell archive, meaning:
  19. # 1. Remove everything above the #! /bin/sh line.
  20. # 2. Save the resulting text in a file.
  21. # 3. Execute the file with /bin/sh (not csh) to create the files:
  22. #    LabelGadge.c
  23. #    Menu.c
  24. #    MenuItem.c
  25. #    MinMax.c
  26. #    Pushbutton.c
  27. # This archive created: Wed Oct 24 14:25:59 1990
  28. export PATH; PATH=/bin:$PATH
  29. echo shar: extracting "'LabelGadge.c'" '(12890 characters)'
  30. if test -f 'LabelGadge.c'
  31. then
  32.     echo shar: will not over-write existing file "'LabelGadge.c'"
  33. else
  34. sed 's/^    X//' << \SHAR_EOF > 'LabelGadge.c'
  35.     X/***********************************************************
  36.     XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  37.     X
  38.     X                        All Rights Reserved
  39.     X
  40.     XPermission to use, copy, modify, and distribute these examples for any
  41.     Xpurpose and without fee is hereby granted, provided that the above
  42.     Xcopyright notice appear in all copies and that both that copyright
  43.     Xnotice and this permission notice appear in supporting documentation,
  44.     Xand that the name of Digital not be used in advertising or publicity
  45.     Xpertaining to distribution of the software without specific, written
  46.     Xprior permission.
  47.     X
  48.     XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  49.     XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  50.     XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  51.     XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  52.     XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  53.     XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  54.     XOR PERFORMANCE OF THIS SOFTWARE.
  55.     X
  56.     X******************************************************************/
  57.     X
  58.     X#include <string.h>        /* Needed for string manipulation */
  59.     X#include <X11/IntrinsicP.h>    /* Intrinsics header file */
  60.     X#include <X11/StringDefs.h>    /* Resource string definitions */
  61.     X#include "LabelGadgP.h"        /* LabelGadget private header file */
  62.     X
  63.     X#define Offset(field) XtOffsetOf(LabelGadgetRec, label.field)
  64.     X
  65.     Xstatic XtResource resources[] = {
  66.     X    {XtNlabel, XtCLabel, XtRString, sizeof(String),
  67.     X    Offset(label), XtRString, (XtPointer) NULL},
  68.     X    {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  69.     X    Offset(font), XtRString, (XtPointer) XtDefaultFont},
  70.     X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  71.     X    Offset(foreground), XtRString,
  72.     X    (XtPointer) XtDefaultForeground},
  73.     X    {XtNjustify, XtCJustify, XtRJustify, sizeof(Justify),
  74.     X    Offset(justify), XtRImmediate, (XtPointer) Left},
  75.     X    {XtNspace, XtCSpace, XtRDimension, sizeof(Dimension),
  76.     X    Offset(space), XtRImmediate, (XtPointer) 2},
  77.     X    {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
  78.     X         XtOffsetOf(LabelGadgetRec, rectObj.border_width),
  79.     X     XtRImmediate, (XtPointer) 0},
  80.     X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
  81.     X    Offset(background), XtRString,
  82.     X    (XtPointer) XtDefaultBackground},
  83.     X    {XtNborderColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
  84.     X    Offset(border), XtRString, (XtPointer) XtDefaultForeground},
  85.     X};
  86.     X#undef Offset
  87.     X
  88.     X/* Forward declarations */
  89.     X
  90.     Xstatic void ClassInitialize(), Initialize(),
  91.     X    Redisplay(), Destroy(), Resize();
  92.     Xstatic Boolean SetValues();
  93.     Xstatic XtGeometryResult QueryGeometry();
  94.     X
  95.     X/* Class record declaration */
  96.     X
  97.     XLabelGadgetClassRec labelGadgetClassRec = {
  98.     X    /* RectObj class part */
  99.     X  {
  100.     X    /* superclass         */    (WidgetClass) &rectObjClassRec,
  101.     X    /* class_name         */    "LabelGadget",
  102.     X    /* widget_size         */    sizeof(LabelGadgetRec),
  103.     X    /* class_initialize      */ ClassInitialize,
  104.     X    /* class_part_initialize */    NULL,
  105.     X    /* class_inited          */    FALSE,
  106.     X    /* initialize         */    Initialize,
  107.     X    /* initialize_hook       */    NULL,        
  108.     X    /* rect1             */    NULL,
  109.     X    /* rect2             */    NULL,
  110.     X    /* rect3             */    0,
  111.     X    /* resources         */    resources,
  112.     X    /* num_resources         */    XtNumber(resources),
  113.     X    /* xrm_class         */    NULLQUARK,
  114.     X    /* rect4             */    0,
  115.     X    /* rect5             */    0,
  116.     X    /* rect6             */    0,
  117.     X    /* rect7             */    0,
  118.     X    /* destroy             */    Destroy,
  119.     X    /* resize             */    Resize,
  120.     X    /* expose             */    Redisplay,
  121.     X    /* set_values         */    SetValues,
  122.     X    /* set_values_hook       */    NULL,            
  123.     X    /* set_values_almost     */    XtInheritSetValuesAlmost,  
  124.     X    /* get_values_hook       */    NULL,            
  125.     X    /* rect9             */    NULL,
  126.     X    /* version             */    XtVersion,
  127.     X    /* callback offsets      */ NULL,
  128.     X    /* rect10             */ NULL,
  129.     X    /* query_geometry         */    QueryGeometry,
  130.     X    /* rect11             */ NULL,
  131.     X    /* extension             */ NULL
  132.     X  },
  133.     X    /* LabelGadget class part    */
  134.     X  {
  135.     X    /* extension             */ NULL
  136.     X  }
  137.     X};
  138.     X
  139.     X/* Class record pointer */
  140.     X
  141.     XWidgetClass labelGadgetClass = (WidgetClass) &labelGadgetClassRec;
  142.     X
  143.     Xstatic void ClassInitialize()
  144.     X{
  145.     X    extern void CvtStringToJustify();    /* Defined in Label.c */
  146.     X
  147.     X    /* Register a converter for string to justification */
  148.     X
  149.     X    XtSetTypeConverter(XtRString, XtRJustify, CvtStringToJustify,
  150.     X            (XtConvertArgList) NULL, 0,
  151.     X        XtCacheAll, (XtDestructor) NULL);
  152.     X}
  153.     X
  154.     Xstatic void SetTextWidthAndHeight(lw)
  155.     X    LabelGadget lw;
  156.     X{
  157.     X    register XFontStruct *fs = lw->label.font;
  158.     X
  159.     X    /* Compute the text dimensions based on the string and the font */
  160.     X
  161.     X    lw->label.label_len = strlen(lw->label.label);
  162.     X    lw->label.label_width =
  163.     X        XTextWidth(fs, lw->label.label, lw->label.label_len);
  164.     X    lw->label.label_height =
  165.     X        fs->max_bounds.ascent + fs->max_bounds.descent;
  166.     X}
  167.     X
  168.     Xstatic GC GetNormalGC(lw)
  169.     X    LabelGadget lw;
  170.     X{
  171.     X    XGCValues    values;
  172.     X
  173.     X    /* Allocate a graphics context with the foreground and font */
  174.     X
  175.     X    values.foreground = lw->label.foreground;
  176.     X    values.font = lw->label.font->fid;
  177.     X    return XtGetGC((Widget) lw, GCForeground | GCFont, &values);
  178.     X}
  179.     X
  180.     Xstatic GC GetBackgroundGC(lw)
  181.     X    LabelGadget lw;
  182.     X{
  183.     X    XGCValues    values;
  184.     X
  185.     X    /* Allocate a graphics context with the background */
  186.     X
  187.     X    values.foreground = lw->label.background;
  188.     X    return XtGetGC((Widget) lw, GCForeground, &values);
  189.     X}
  190.     X
  191.     Xstatic GC GetBorderGC(lw)
  192.     X    LabelGadget lw;
  193.     X{
  194.     X    XGCValues    values;
  195.     X
  196.     X    if (lw->rectObj.border_width == 0) return NULL;
  197.     X
  198.     X    /* Allocate a graphics context with the border values */
  199.     X
  200.     X    values.foreground = lw->label.border;
  201.     X    values.line_width = lw->rectObj.border_width;
  202.     X    return XtGetGC((Widget) lw, GCForeground | GCLineWidth, &values);
  203.     X}
  204.     X
  205.     Xstatic void Initialize(request, new, args, num_args)
  206.     X    Widget request, new;
  207.     X    ArgList args;
  208.     X    Cardinal *num_args;
  209.     X{
  210.     X    LabelGadget lw = (LabelGadget) new;
  211.     X
  212.     X    /* If no label is specified, use the name */
  213.     X    if (lw->label.label == NULL) lw->label.label = XtName(lw);
  214.     X
  215.     X    /* Copy the label */
  216.     X    lw->label.label = XtNewString(lw->label.label);
  217.     X
  218.     X    /* Compute the text dimensions and get graphics contexts. */
  219.     X    SetTextWidthAndHeight(lw);
  220.     X    lw->label.gc = lw->label.current_gc = GetNormalGC(lw);
  221.     X    lw->label.background_gc =
  222.     X        lw->label.current_bg_gc = GetBackgroundGC(lw);
  223.     X    lw->label.border_gc = GetBorderGC(lw);
  224.     X
  225.     X    /* If no size specified, compute one */
  226.     X    lw->label.size_computed =
  227.     X        (lw->rectObj.width == 0) && (lw->rectObj.height == 0);
  228.     X
  229.     X    if (lw->rectObj.width == 0) {
  230.     X    lw->rectObj.width = lw->label.label_width +
  231.     X        2 * lw->label.space;
  232.     X    }
  233.     X    if (lw->rectObj.height == 0) {
  234.     X    lw->rectObj.height = lw->label.label_height +
  235.     X        2 * lw->label.space;
  236.     X    }
  237.     X
  238.     X    lw->label.old_border = lw->rectObj.border_width;
  239.     X
  240.     X    lw->label.desired_width = lw->rectObj.width;
  241.     X    lw->label.desired_height = lw->rectObj.height;
  242.     X}
  243.     X
  244.     Xstatic Boolean SetValues(old, request, new, args, num_args)
  245.     X    Widget  old, request, new;
  246.     X    ArgList args;
  247.     X    Cardinal *num_args;
  248.     X{
  249.     X    LabelGadget oldlw = (LabelGadget) old;
  250.     X    LabelGadget newlw = (LabelGadget) new;
  251.     X    Boolean redisplay = FALSE;
  252.     X
  253.     X#define NE(field) (oldlw->field != newlw->field)
  254.     X
  255.     X    /* If the label has been reset to NULL, change to the name */
  256.     X
  257.     X    if (newlw->label.label == NULL) {
  258.     X    newlw->label.label = XtName(newlw);
  259.     X    }
  260.     X
  261.     X    /* Decide whether to compute the size */
  262.     X
  263.     X    if (newlw->rectObj.width == 0 && newlw->rectObj.height == 0) {
  264.     X    newlw->label.size_computed = TRUE;
  265.     X    } else if (NE(rectObj.width) || NE(rectObj.height)) {
  266.     X    newlw->label.size_computed = FALSE;
  267.     X    if (NE(rectObj.width)) {
  268.     X        newlw->label.desired_width = newlw->rectObj.width;
  269.     X    }
  270.     X    if (NE(rectObj.height)) {
  271.     X        newlw->label.desired_height = newlw->rectObj.height;
  272.     X    }
  273.     X    } /* else leave the same */
  274.     X
  275.     X    /* If label, or font has changed, recopy and compute size */
  276.     X
  277.     X    if (NE(label.label) || NE(label.font)) {
  278.     X    if (NE(label.label)) {
  279.     X        XtFree((char *) oldlw->label.label);
  280.     X        newlw->label.label = XtNewString(newlw->label.label);
  281.     X    }
  282.     X    SetTextWidthAndHeight(newlw);
  283.     X    redisplay = TRUE;
  284.     X    }
  285.     X
  286.     X    /* Compute the size if necessary */
  287.     X
  288.     X    if (newlw->label.size_computed || newlw->rectObj.width == 0) {
  289.     X    newlw->label.desired_width = newlw->rectObj.width =
  290.     X        newlw->label.label_width + 2 * newlw->label.space;
  291.     X    }
  292.     X    if (newlw->label.size_computed || newlw->rectObj.height == 0) {
  293.     X    newlw->label.desired_height = newlw->rectObj.height =
  294.     X        newlw->label.label_height + 2 * newlw->label.space;
  295.     X    }
  296.     X    
  297.     X    /* If foreground or font has changed, update GC */
  298.     X
  299.     X    if (NE(label.foreground) || NE(label.font->fid)) {
  300.     X    XtReleaseGC(newlw, oldlw->label.gc);
  301.     X    newlw->label.gc = GetNormalGC(newlw);
  302.     X
  303.     X    if (newlw->label.current_gc == oldlw->label.gc) {
  304.     X        newlw->label.current_gc = newlw->label.gc;
  305.     X        redisplay = TRUE;
  306.     X    }
  307.     X    }
  308.     X
  309.     X    /* If background has changed, update background GC */
  310.     X
  311.     X    if (NE(label.background)) {
  312.     X    XtReleaseGC(newlw, oldlw->label.background_gc);
  313.     X    newlw->label.background_gc = GetBackgroundGC(newlw);
  314.     X
  315.     X    if (newlw->label.current_bg_gc == oldlw->label.background_gc) {
  316.     X        newlw->label.current_bg_gc = newlw->label.background_gc;
  317.     X        redisplay = TRUE;
  318.     X    }
  319.     X    }
  320.     X
  321.     X    /* If border has changed, update border GC */
  322.     X
  323.     X    if (NE(label.border) || NE(rectObj.border_width)) {
  324.     X    if (oldlw->label.border_gc != NULL) {
  325.     X        XtReleaseGC(newlw, oldlw->label.border_gc);
  326.     X    }
  327.     X    newlw->label.border_gc = GetBorderGC(newlw);
  328.     X    redisplay = TRUE;
  329.     X    }
  330.     X
  331.     X    return redisplay || NE(label.space) || NE(label.justify);
  332.     X#undef NE
  333.     X}
  334.     X
  335.     Xstatic void Destroy(w)
  336.     X    Widget w;
  337.     X{
  338.     X    LabelGadget lw = (LabelGadget) w;
  339.     X
  340.     X    XtFree((char *) lw->label.label);
  341.     X
  342.     X    XtReleaseGC(w, lw->label.gc);
  343.     X    XtReleaseGC(w, lw->label.background_gc);
  344.     X    if (lw->label.border_gc != NULL) {
  345.     X    XtReleaseGC(w, lw->label.border_gc);
  346.     X    }
  347.     X}
  348.     X
  349.     Xstatic void Redisplay(w, event, region)
  350.     X    Widget w;
  351.     X    XEvent *event;
  352.     X    Region region;
  353.     X{
  354.     X    LabelGadget lw = (LabelGadget) w;
  355.     X    int offset, x;
  356.     X    XRectangle rect;
  357.     X    Region r1, r2;
  358.     X
  359.     X    /* Draw the background */
  360.     X    XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  361.     X            lw->label.current_bg_gc,
  362.     X        lw->rectObj.x + lw->rectObj.border_width,
  363.     X        lw->rectObj.y + lw->rectObj.border_width,
  364.     X        lw->rectObj.width, lw->rectObj.height);
  365.     X
  366.     X    /* Draw the border */
  367.     X    if (lw->rectObj.border_width != 0) {
  368.     X    offset = lw->rectObj.border_width / 2;
  369.     X    XDrawRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
  370.     X        lw->label.border_gc,
  371.     X        lw->rectObj.x + offset, lw->rectObj.y + offset,
  372.     X        lw->rectObj.width + lw->rectObj.border_width,
  373.     X        lw->rectObj.height + lw->rectObj.border_width);
  374.     X    }
  375.     X
  376.     X    switch (lw->label.justify) {
  377.     X    case Left:
  378.     X        x = lw->label.space;    
  379.     X        break;
  380.     X    case Right:
  381.     X        x = (int) lw->rectObj.width - (int) lw->label.space -
  382.     X            (int) lw->label.label_width;
  383.     X        break;
  384.     X    case Center:
  385.     X        x = ((int) lw->rectObj.width -
  386.     X            (int) lw->label.label_width) / 2;
  387.     X        break;
  388.     X    }
  389.     X
  390.     X    /* Temporarily change the clip mask in the gc */
  391.     X    rect.x = lw->rectObj.x + lw->rectObj.border_width;
  392.     X    rect.y = lw->rectObj.y + lw->rectObj.border_width;
  393.     X    rect.width = lw->rectObj.width;
  394.     X    rect.height = lw->rectObj.height;
  395.     X
  396.     X    r1 = XCreateRegion();
  397.     X    r2 = XCreateRegion();
  398.     X    if (region != NULL) {
  399.     X    XUnionRectWithRegion(&rect, r1, r2);    /* r2 = rectangle */
  400.     X    XIntersectRegion(region, r2, r1);    /* r1 = intersection */
  401.     X    } else XUnionRectWithRegion(&rect, r2, r1); /* r1 = rectangle */
  402.     X
  403.     X    XSetRegion(XtDisplayOfObject(w), lw->label.current_gc, r1);
  404.     X    XDestroyRegion(r1);
  405.     X    XDestroyRegion(r2);
  406.     X
  407.     X    XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
  408.     X        lw->label.current_gc,
  409.     X        lw->rectObj.x + lw->rectObj.border_width + x,
  410.     X        lw->rectObj.y + lw->rectObj.border_width + 
  411.     X        lw->label.space + lw->label.font->max_bounds.ascent,
  412.     X        lw->label.label, lw->label.label_len);
  413.     X
  414.     X    /* Restore the GC */
  415.     X    XSetClipMask(XtDisplayOfObject(w), lw->label.current_gc, None);
  416.     X}
  417.     X
  418.     Xstatic void Resize(w)
  419.     X    Widget w;
  420.     X{
  421.     X    LabelGadget lw = (LabelGadget) w;
  422.     X
  423.     X    /* If border width changed, update border GC */
  424.     X
  425.     X    if (lw->label.old_border != lw->rectObj.border_width) {
  426.     X    if (lw->label.border_gc != NULL) {
  427.     X        XtReleaseGC(w, lw->label.border_gc);
  428.     X    }
  429.     X    lw->label.border_gc = GetBorderGC(lw);
  430.     X    lw->label.old_border = lw->rectObj.border_width;
  431.     X    }
  432.     X}   
  433.     X
  434.     Xstatic XtGeometryResult QueryGeometry(w, proposed, desired)
  435.     X    Widget w;
  436.     X    XtWidgetGeometry *proposed, *desired;
  437.     X{
  438.     X    LabelGadget lw = (LabelGadget) w;
  439.     X#define Set(bit) (proposed->request_mode & bit)
  440.     X
  441.     X    desired->width = lw->label.desired_width;
  442.     X    desired->height = lw->label.desired_height;
  443.     X    desired->request_mode = CWWidth | CWHeight;
  444.     X
  445.     X    if (Set(CWWidth) && proposed->width == desired->width &&
  446.     X        Set(CWHeight) && proposed->height == desired->height) {
  447.     X    return XtGeometryYes;
  448.     X    }
  449.     X
  450.     X    if (desired->width == lw->rectObj.width &&
  451.     X        desired->height == lw->rectObj.height) {
  452.     X    return XtGeometryNo;
  453.     X    }
  454.     X    return XtGeometryAlmost;
  455.     X#undef Set
  456.     X}
  457. SHAR_EOF
  458. if test 12890 -ne "`wc -c < 'LabelGadge.c'`"
  459. then
  460.     echo shar: error transmitting "'LabelGadge.c'" '(should have been 12890 characters)'
  461. fi
  462. fi # end of overwriting check
  463. echo shar: extracting "'Menu.c'" '(18170 characters)'
  464. if test -f 'Menu.c'
  465. then
  466.     echo shar: will not over-write existing file "'Menu.c'"
  467. else
  468. sed 's/^    X//' << \SHAR_EOF > 'Menu.c'
  469.     X/***********************************************************
  470.     XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  471.     X
  472.     X                        All Rights Reserved
  473.     X
  474.     XPermission to use, copy, modify, and distribute these examples for any
  475.     Xpurpose and without fee is hereby granted, provided that the above
  476.     Xcopyright notice appear in all copies and that both that copyright
  477.     Xnotice and this permission notice appear in supporting documentation,
  478.     Xand that the name of Digital not be used in advertising or publicity
  479.     Xpertaining to distribution of the software without specific, written
  480.     Xprior permission.
  481.     X
  482.     XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  483.     XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  484.     XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  485.     XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  486.     XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  487.     XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  488.     XOR PERFORMANCE OF THIS SOFTWARE.
  489.     X
  490.     X******************************************************************/
  491.     X
  492.     X#include <X11/IntrinsicP.h>    /* Intrinsics header file */
  493.     X#include <X11/StringDefs.h>    /* Resource string definitions */
  494.     X#include "MenuP.h"        /* Menu private header file */
  495.     X#include "LabelGadge.h"        /* To check LabelGadgets */
  496.     X
  497.     Xstatic Cardinal InsertBefore();
  498.     X
  499.     Xstatic XtResource resources[] = {
  500.     X    {XtNinsertPosition, XtCInsertPosition,
  501.     X    XtRFunction, sizeof(XtOrderProc),
  502.     X        XtOffsetOf(MenuRec, composite.insert_position),
  503.     X    XtRImmediate, (XtPointer) InsertBefore}
  504.     X};
  505.     X
  506.     Xstatic Cardinal InsertBefore(w)
  507.     X    Widget w;
  508.     X{
  509.     X    MenuWidget menu = (MenuWidget) XtParent(w);
  510.     X    MenuConstraint mc = (MenuConstraint) w->core.constraints;
  511.     X    int i;
  512.     X
  513.     X    if (mc->menu.insert_before == NULL) {
  514.     X    return menu->composite.num_children;
  515.     X    }
  516.     X
  517.     X    for (i = 0; i < menu->composite.num_children; i++) {
  518.     X    if (mc->menu.insert_before == menu->composite.children[i]) {
  519.     X        return i;
  520.     X    }
  521.     X    }
  522.     X
  523.     X    return menu->composite.num_children;
  524.     X}
  525.     X
  526.     Xstatic XtResource constraintResources[] = {
  527.     X    {XtNinsertBefore, XtCInsertBefore, XtRWidget, sizeof(Widget),
  528.     X    XtOffsetOf(MenuConstraintRec, menu.insert_before), 
  529.     X    XtRImmediate, NULL},
  530.     X};
  531.     X
  532.     X/* Forward declarations */
  533.     X
  534.     Xstatic void ClassInitialize(), ChangeManaged(), Initialize(),
  535.     X    ConstraintInitialize(), Resize(), InsertChild(),
  536.     X    Redisplay(), Destroy(), ConstraintGetValuesHook();
  537.     Xstatic XtGeometryResult GeometryManager();
  538.     Xstatic Boolean ConstraintSetValues();
  539.     X
  540.     Xstatic CompositeClassExtensionRec compositeExtension = {
  541.     X    /* next_extension        */ NULL,
  542.     X    /* record_type        */ NULLQUARK,
  543.     X    /* version            */ XtCompositeExtensionVersion,
  544.     X    /* record_size        */ sizeof(CompositeClassExtensionRec),
  545.     X    /* accepts_objects        */ TRUE
  546.     X};
  547.     X
  548.     Xstatic ConstraintClassExtensionRec constraintExtension = {
  549.     X    /* next_extension        */ NULL,
  550.     X    /* record_type        */ NULLQUARK,
  551.     X    /* version            */ XtConstraintExtensionVersion,
  552.     X    /* record_size        */ sizeof(ConstraintClassExtensionRec),
  553.     X    /* get_values_hook        */ ConstraintGetValuesHook
  554.     X};
  555.     X
  556.     XMenuClassRec menuClassRec = {
  557.     X    /* Core class part */
  558.     X  {
  559.     X    /* superclass         */    (WidgetClass) &constraintClassRec,
  560.     X    /* class_name         */ "Menu",
  561.     X    /* widget_size         */ sizeof(MenuRec),
  562.     X    /* class_initialize      */ ClassInitialize,
  563.     X    /* class_part_initialize */ NULL,
  564.     X    /* class_inited          */    FALSE,
  565.     X    /* initialize         */    Initialize,
  566.     X    /* initialize_hook       */    NULL,
  567.     X    /* realize             */    XtInheritRealize,
  568.     X    /* actions             */    NULL,
  569.     X    /* num_actions         */    0,
  570.     X    /* resources         */    resources,
  571.     X    /* num_resources         */    XtNumber(resources),
  572.     X    /* xrm_class         */    NULLQUARK,
  573.     X    /* compress_motion         */    TRUE,
  574.     X    /* compress_exposure     */    XtExposeCompressMultiple,
  575.     X    /* compress_enterleave   */    TRUE,
  576.     X    /* visible_interest         */    FALSE,
  577.     X    /* destroy             */    Destroy,
  578.     X    /* resize             */    Resize,
  579.     X    /* expose             */    Redisplay,
  580.     X    /* set_values         */    NULL,
  581.     X    /* set_values_hook       */    NULL,            
  582.     X    /* set_values_almost     */    XtInheritSetValuesAlmost,  
  583.     X    /* get_values_hook       */    NULL,            
  584.     X    /* accept_focus         */    NULL,
  585.     X    /* version             */    XtVersion,
  586.     X    /* callback offsets      */    NULL,
  587.     X    /* tm_table              */    NULL,
  588.     X    /* query_geometry         */    XtInheritQueryGeometry,
  589.     X    /* display_accelerator   */    NULL,
  590.     X    /* extension         */    NULL,
  591.     X  },
  592.     X   /* Composite class part */
  593.     X  {
  594.     X    /* geometry_manager         */    GeometryManager,
  595.     X    /* change_managed         */    ChangeManaged,
  596.     X    /* insert_child         */    InsertChild,
  597.     X    /* delete_child         */    XtInheritDeleteChild,
  598.     X    /* extension         */    (XtPointer) &compositeExtension,
  599.     X  },
  600.     X   /* Constraint class part */
  601.     X  {
  602.     X   /* resources             */ constraintResources,
  603.     X   /* num_resources         */ XtNumber(constraintResources),
  604.     X   /* constraint_size         */ sizeof(MenuConstraintRec),
  605.     X   /* initialize         */ ConstraintInitialize,
  606.     X   /* destroy             */ NULL,
  607.     X   /* set_values         */ ConstraintSetValues,
  608.     X   /* extension             */ (XtPointer) &constraintExtension,
  609.     X  },
  610.     X   /* Menu class part */
  611.     X  {
  612.     X    /* extension         */    NULL,
  613.     X  }
  614.     X};
  615.     X
  616.     XWidgetClass menuWidgetClass = (WidgetClass) &menuClassRec;
  617.     X
  618.     Xstatic void InsertChild(w)
  619.     X    Widget w;
  620.     X{
  621.     X    String params[2];
  622.     X    Cardinal num_params;
  623.     X    Widget parent = XtParent(w);
  624.     X
  625.     X    if (!XtIsWidget(w) && !XtIsSubclass(w, labelGadgetClass)) {
  626.     X    params[0] = XtClass(w)->core_class.class_name;
  627.     X    params[1] = XtClass(parent)->core_class.class_name;
  628.     X    num_params = 2;
  629.     X    XtAppErrorMsg(XtWidgetToApplicationContext(w),
  630.     X        "childError", "class", "WidgetError",
  631.     X        "Children of class %s cannot be added to %n widgets",
  632.     X        params, &num_params);
  633.     X    }
  634.     X
  635.     X    (*((CompositeWidgetClass)(menuWidgetClass->
  636.     X        core_class.superclass))->composite_class.insert_child) (w);
  637.     X}
  638.     X
  639.     Xstatic Boolean CvtStringToWidget(dpy, args, num_args, from, to, data)
  640.     X    Display *dpy;
  641.     X    XrmValuePtr args;
  642.     X    Cardinal *num_args;
  643.     X    XrmValuePtr from, to;
  644.     X    XtPointer *data;
  645.     X{
  646.     X    static Widget w;
  647.     X    Widget parent;
  648.     X    Boolean badConvert;
  649.     X
  650.     X    if (*num_args != 1) {
  651.     X    XtAppErrorMsg(XtDisplayToApplicationContext(dpy),
  652.     X        "wrongParameters", "cvtStringToWidget",
  653.     X        "XtToolkitError",
  654.     X        "StringToWidget conversion needs parent arg",
  655.     X        (String *) NULL, (Cardinal *) NULL);
  656.     X    }
  657.     X
  658.     X    /* Convert first arg into parent */
  659.     X
  660.     X    parent = *(Widget*) args[0].addr;
  661.     X
  662.     X    w = XtNameToWidget(parent, (String) from->addr);
  663.     X    badConvert = (w == NULL);
  664.     X
  665.     X    if (badConvert) {
  666.     X        XtDisplayStringConversionWarning(dpy, from->addr, "Widget");
  667.     X    } else {
  668.     X    if (to->addr == NULL) to->addr = (caddr_t) &w;
  669.     X    else if (to->size < sizeof(Widget)) badConvert = TRUE;
  670.     X    else *(Widget *) to->addr = w;
  671.     X
  672.     X    to->size = sizeof(Widget);
  673.     X    }
  674.     X    return !badConvert;
  675.     X}
  676.     X
  677.     Xstatic void ClassInitialize()
  678.     X{
  679.     X    static XtConvertArgRec parentConvertArgs[] = {
  680.     X    {XtBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.parent),
  681.     X        sizeof(Widget)},
  682.     X    };
  683.     X
  684.     X
  685.     X    /* Register a converter for string to widget */
  686.     X
  687.     X    XtSetTypeConverter(XtRString, XtRWidget, CvtStringToWidget,
  688.     X        parentConvertArgs, XtNumber(parentConvertArgs),
  689.     X        XtCacheNone, (XtDestructor) NULL);
  690.     X}
  691.     X
  692.     Xstatic void HandleMenuButton(w, client_data, event,
  693.     X    continue_to_dispatch)
  694.     X    Widget w;
  695.     X    XtPointer client_data;
  696.     X    XEvent *event;
  697.     X    Boolean *continue_to_dispatch;
  698.     X{
  699.     X    switch (event->type) {
  700.     X    case ButtonPress:
  701.     X        /* The new grab does an implicit AllowEvents */
  702.     X        (void) XtGrabPointer(w, True,
  703.     X            EnterWindowMask | LeaveWindowMask | 
  704.     X                ButtonReleaseMask,
  705.     X            GrabModeAsync, GrabModeAsync, None, None,
  706.     X            event->xbutton.time);
  707.     X        break;
  708.     X
  709.     X    case ButtonRelease:
  710.     X        /* Popping down also ungrabs the pointer */
  711.     X        XtPopdown(w);
  712.     X        break;
  713.     X    }
  714.     X}
  715.     X
  716.     Xstatic void Initialize(req, new)
  717.     X    Widget req, new;
  718.     X{
  719.     X    ((MenuWidget) new)->menu.save_border = -1;
  720.     X
  721.     X    if (XtIsShell(XtParent(new))) {
  722.     X    XtAddRawEventHandler(XtParent(new),
  723.     X        ButtonPressMask | ButtonReleaseMask,
  724.     X        FALSE, HandleMenuButton, NULL);
  725.     X    }
  726.     X}
  727.     X
  728.     Xstatic void ConstraintInitialize(req, new, args, num_args)
  729.     X    Widget req, new;
  730.     X    ArgList args;
  731.     X    Cardinal *num_args;
  732.     X{
  733.     X    MenuConstraint mc = (MenuConstraint) new->core.constraints;
  734.     X
  735.     X    mc->menu.desired_height = new->core.height;
  736.     X    mc->menu.desired_border_width = new->core.border_width;
  737.     X}
  738.     X
  739.     Xstatic void Destroy(w)
  740.     X    Widget w;
  741.     X{
  742.     X    XtRemoveRawEventHandler(XtParent(w), XtAllEvents, TRUE,
  743.     X        HandleMenuButton, NULL);
  744.     X}
  745.     X
  746.     Xstatic void PositionChildren(menu, initiator)
  747.     X    register MenuWidget menu;
  748.     X    Widget initiator;
  749.     X{
  750.     X    int i, y;
  751.     X    register int last_border;
  752.     X    register Widget child;
  753.     X    MenuConstraint mc;
  754.     X    Boolean first = TRUE;
  755.     X
  756.     X    if (menu->composite.num_children == 0) return;
  757.     X
  758.     X    for (i = 0; i < menu->composite.num_children; i++) {
  759.     X    child = menu->composite.children[i];
  760.     X    if (!XtIsManaged(child)) continue;
  761.     X    mc = (MenuConstraint) child->core.constraints;
  762.     X
  763.     X    if (first) {
  764.     X        first = FALSE;
  765.     X        last_border = mc->menu.desired_border_width;
  766.     X        y = -last_border;
  767.     X    }
  768.     X
  769.     X    if (child == initiator) {
  770.     X        if (last_border > child->core.border_width) {
  771.     X        y += last_border - child->core.border_width;
  772.     X        }
  773.     X        last_border = child->core.border_width;
  774.     X
  775.     X        child->core.x = -last_border;
  776.     X        child->core.y = y;
  777.     X        child->core.width = menu->core.width;
  778.     X    } else {
  779.     X        if (last_border > mc->menu.desired_border_width) {
  780.     X        y += last_border - mc->menu.desired_border_width;
  781.     X        }
  782.     X        last_border = mc->menu.desired_border_width;
  783.     X
  784.     X        XtConfigureWidget(child, -last_border, y,
  785.     X            menu->core.width, mc->menu.desired_height,
  786.     X            last_border);
  787.     X    }
  788.     X
  789.     X    y += (int) child->core.height + last_border;
  790.     X    }
  791.     X}
  792.     X
  793.     Xstatic void Resize(w)
  794.     X    Widget w;
  795.     X{
  796.     X    PositionChildren((MenuWidget) w, (Widget) NULL);
  797.     X}
  798.     X
  799.     Xstatic int WidestDesiredSize(menu, initiator)
  800.     X    MenuWidget menu;
  801.     X    Widget initiator;
  802.     X{
  803.     X    register int i, width = 0;
  804.     X    register Widget child;
  805.     X    XtWidgetGeometry desired;
  806.     X
  807.     X    for (i = 0; i < menu->composite.num_children; i++) {
  808.     X        child = menu->composite.children[i];
  809.     X    if (!XtIsManaged(child)) continue;
  810.     X
  811.     X    if (child == initiator) {
  812.     X        if (child->core.width > width) {
  813.     X        width = child->core.width;
  814.     X        }
  815.     X    } else {
  816.     X        (void) XtQueryGeometry(child, NULL, &desired);
  817.     X        if (desired.width > width) width = desired.width;
  818.     X    }
  819.     X    }
  820.     X
  821.     X    if (width <= 0) return 1;
  822.     X    else return width;
  823.     X}
  824.     X
  825.     Xstatic void CalculateDesiredSizes(menu, width, initiator)
  826.     X    MenuWidget menu;
  827.     X    Dimension width;
  828.     X    Widget initiator;
  829.     X{
  830.     X    XtWidgetGeometry proposed, desired;
  831.     X    register Widget child;
  832.     X    MenuConstraint mc;
  833.     X    register int i;
  834.     X
  835.     X    for (i = 0; i < menu->composite.num_children; i++) {
  836.     X        child = menu->composite.children[i];
  837.     X    if (!XtIsManaged(child)) continue;
  838.     X    mc = (MenuConstraint) child->core.constraints;
  839.     X
  840.     X    if (child == initiator) {
  841.     X        mc->menu.desired_height = child->core.height;
  842.     X        mc->menu.desired_border_width = 
  843.     X            child->core.border_width;
  844.     X    } else {
  845.     X        proposed.width = width;
  846.     X        proposed.request_mode = CWWidth;
  847.     X        (void) XtQueryGeometry(child, &proposed, &desired);
  848.     X
  849.     X        mc->menu.desired_height = desired.height;
  850.     X        mc->menu.desired_border_width = desired.border_width;
  851.     X    }
  852.     X    }
  853.     X}
  854.     X
  855.     Xstatic void CalculateNewSize(menu, width, height, initiator)
  856.     X    register MenuWidget menu;
  857.     X    Dimension *width, *height;
  858.     X    Widget initiator;
  859.     X{
  860.     X    register int i;
  861.     X    register int last_border;
  862.     X    register Widget child;
  863.     X    int y;
  864.     X    MenuConstraint mc;
  865.     X    Boolean first = TRUE;
  866.     X
  867.     X    if (menu->composite.num_children == 0) {
  868.     X    *width = *height = 10;    /* Arbitrary */
  869.     X    return;
  870.     X    }
  871.     X
  872.     X    *width = WidestDesiredSize(menu, initiator);
  873.     X
  874.     X    CalculateDesiredSizes(menu, *width, initiator);
  875.     X
  876.     X    for (i = 0; i < menu->composite.num_children; i++) {
  877.     X        child = menu->composite.children[i];
  878.     X    if (!XtIsManaged(child)) continue;
  879.     X    mc = (MenuConstraint) child->core.constraints;
  880.     X
  881.     X    if (first) {
  882.     X        first = FALSE;
  883.     X        last_border = mc->menu.desired_border_width;
  884.     X        y = -last_border;
  885.     X    }
  886.     X
  887.     X    if (last_border > mc->menu.desired_border_width) {
  888.     X        y += last_border - (int) mc->menu.desired_border_width;
  889.     X    }
  890.     X    last_border = mc->menu.desired_border_width;
  891.     X    y += (int) mc->menu.desired_height + last_border;
  892.     X    }    
  893.     X    
  894.     X    if (y <= 0) y = 1;
  895.     X    *height = y;
  896.     X}
  897.     X
  898.     Xstatic void ChangeManaged(w)
  899.     X    Widget w;
  900.     X{
  901.     X    MenuWidget menu = (MenuWidget) w;
  902.     X    XtWidgetGeometry request;
  903.     X    XtGeometryResult result;
  904.     X
  905.     X    CalculateNewSize(menu, &request.width, &request.height,
  906.     X        (Widget) NULL);
  907.     X
  908.     X    if (request.width != menu->core.width ||
  909.     X        request.height != menu->core.height) {
  910.     X    request.request_mode = CWWidth | CWHeight;
  911.     X    do {
  912.     X        result = XtMakeGeometryRequest(w, &request, &request);
  913.     X    } while (result == XtGeometryAlmost);
  914.     X    }
  915.     X
  916.     X    PositionChildren(menu, (Widget) NULL);
  917.     X}
  918.     X
  919.     Xstatic XtGeometryResult GeometryManager(w, desired, allowed)
  920.     X    Widget w;
  921.     X    XtWidgetGeometry *desired, *allowed;
  922.     X{
  923.     X    MenuWidget menu = (MenuWidget) XtParent(w);
  924.     X    XtWidgetGeometry request;
  925.     X    XtGeometryResult result;
  926.     X    Dimension save_width, save_height, save_border_width;
  927.     X
  928.     X#define Wants(flag) (desired->request_mode & flag)
  929.     X#define RestoreGeometry(w) { \
  930.     X    w->core.width = save_width; \
  931.     X    w->core.height = save_height; \
  932.     X        w->core.border_width = save_border_width; }
  933.     X
  934.     X    if (menu->menu.save_border != -1) {
  935.     X    /* This was caused by a child set-values */
  936.     X    w->core.border_width = menu->menu.save_border;
  937.     X    menu->menu.save_border = -1;
  938.     X    desired->border_width -= 1000;
  939.     X    }
  940.     X
  941.     X    if (Wants(CWX) || Wants(CWY)) {
  942.     X    return XtGeometryNo;
  943.     X    }
  944.     X
  945.     X    /* If only requesting a stack mode change, allow it */
  946.     X
  947.     X    if (!Wants(CWWidth) && !Wants(CWHeight) && !Wants(CWBorderWidth)) {
  948.     X    return XtGeometryYes;
  949.     X    }
  950.     X
  951.     X    /* Figure out how big we would be with this change */
  952.     X
  953.     X    save_width = w->core.width;
  954.     X    save_height = w->core.height;
  955.     X    save_border_width = w->core.border_width;
  956.     X    if (Wants(CWWidth)) w->core.width = desired->width;
  957.     X    if (Wants(CWHeight)) w->core.height = desired->height;
  958.     X    if (Wants(CWBorderWidth)) {
  959.     X    w->core.border_width = desired->border_width;
  960.     X    }
  961.     X
  962.     X    CalculateNewSize(menu, &request.width, &request.height, w);
  963.     X
  964.     X    /* If the new width is the same as the old and the child requested
  965.     X       a width change, CalculateNewSize was not able to accommodate
  966.     X       the width change, so refuse the geometry request. */
  967.     X
  968.     X    if (request.width == menu->core.width && Wants(CWWidth)) {
  969.     X    RestoreGeometry(w);
  970.     X    return XtGeometryNo;
  971.     X    }
  972.     X
  973.     X    /* If new width is equal to child's width, we are going to try
  974.     X       to accommodate the child.  Make a geometry request.  This also
  975.     X       covers cases where the child requested no width
  976.     X       change since that wouldn't cause the menu to change width. */
  977.     X
  978.     X    if (request.width == w->core.width) {
  979.     X    request.request_mode = CWWidth | CWHeight;
  980.     X    if (Wants(XtCWQueryOnly)) {
  981.     X        request.request_mode |= XtCWQueryOnly;
  982.     X    }
  983.     X    result = XtMakeGeometryRequest((Widget) menu, &request, NULL);
  984.     X
  985.     X        /* Almost isn't good enough here; must be allowed */
  986.     X
  987.     X    if (result == XtGeometryAlmost) result = XtGeometryNo;
  988.     X    if (result == XtGeometryNo || Wants(XtCWQueryOnly)) {
  989.     X        RestoreGeometry(w);
  990.     X    } else PositionChildren(menu, w);
  991.     X    return result;
  992.     X    }
  993.     X
  994.     X    /* New width is different from child's width, so we want to return
  995.     X       XtGeometryAlmost.  See if this is allowed. */
  996.     X
  997.     X    RestoreGeometry(w);
  998.     X
  999.     X    request.request_mode = CWWidth | CWHeight | XtCWQueryOnly;
  1000.     X    result = XtMakeGeometryRequest((Widget) menu, &request, NULL);
  1001.     X
  1002.     X    /* Almost isn't good enough here; must be allowed */
  1003.     X
  1004.     X    if (result != XtGeometryYes) return XtGeometryNo;
  1005.     X
  1006.     X    /* It would be allowed, so return suggested geometry */
  1007.     X
  1008.     X    *allowed = *desired;
  1009.     X    allowed->width = request.width;
  1010.     X    return XtGeometryAlmost;
  1011.     X#undef Wants
  1012.     X#undef RestoreGeometry
  1013.     X}
  1014.     X
  1015.     Xstatic Boolean ConstraintSetValues(old, req, new, args, num_args)
  1016.     X    Widget old, req, new;
  1017.     X    ArgList args;
  1018.     X    Cardinal *num_args;
  1019.     X{
  1020.     X    MenuConstraint newmc = (MenuConstraint) new->core.constraints;
  1021.     X    MenuConstraint oldmc = (MenuConstraint) old->core.constraints;
  1022.     X    register MenuWidget menu;
  1023.     X    register int i, j;
  1024.     X
  1025.     X    if (newmc->menu.insert_before != oldmc->menu.insert_before) {
  1026.     X    menu = (MenuWidget) XtParent(new);
  1027.     X
  1028.     X    /* Remove child from current position */
  1029.     X
  1030.     X    for (i = 0; i < menu->composite.num_children &&
  1031.     X        menu->composite.children[i] != new; i++) {}
  1032.     X
  1033.     X    for (; i < menu->composite.num_children - 1; i++) {
  1034.     X        menu->composite.children[i] =
  1035.     X            menu->composite.children[i+1];
  1036.     X    }
  1037.     X
  1038.     X    /* Find new widget to insert before */
  1039.     X
  1040.     X    for (i = 0; i < menu->composite.num_children - 1 &&
  1041.     X        menu->composite.children[i] !=
  1042.     X            newmc->menu.insert_before;
  1043.     X        i++) {}
  1044.     X
  1045.     X    /* Move the rest of them up */
  1046.     X
  1047.     X    for (j = menu->composite.num_children - 1; j > i; j--) {
  1048.     X        menu->composite.children[j] =
  1049.     X            menu->composite.children[j-1];
  1050.     X    }
  1051.     X
  1052.     X    menu->composite.children[i] = new;
  1053.     X    
  1054.     X    /* Cause a geometry request */
  1055.     X
  1056.     X    menu->menu.save_border = new->core.border_width;
  1057.     X    new->core.border_width += 1000;
  1058.     X    }
  1059.     X
  1060.     X    return FALSE;
  1061.     X}
  1062.     X
  1063.     Xstatic void Redisplay(w, event, region)
  1064.     X    Widget w;
  1065.     X    XEvent *event;
  1066.     X    Region region;
  1067.     X{
  1068.     X    CompositeWidget comp = (CompositeWidget) w;
  1069.     X    int i;
  1070.     X    Widget c;        /* child */
  1071.     X
  1072.     X    for (i = 0; i < comp->composite.num_children; i++) {
  1073.     X    c = comp->composite.children[i];
  1074.     X    if (XtIsManaged(c) && XtIsSubclass(c, labelGadgetClass) &&
  1075.     X        XRectInRegion(region, c->core.x, c->core.y,
  1076.     X            c->core.width + 2*c->core.border_width,
  1077.     X            c->core.height + 2*c->core.border_width)
  1078.     X            != RectangleOut) {
  1079.     X        (*(XtClass(c)->core_class.expose))(c, event, region);
  1080.     X        }
  1081.     X    }
  1082.     X}
  1083.     X
  1084.     Xstatic void ConstraintGetValuesHook(w, args, num_args)
  1085.     X    Widget w;
  1086.     X    ArgList args;
  1087.     X    Cardinal *num_args;
  1088.     X{
  1089.     X    register int i, j;
  1090.     X
  1091.     X    for (i = 0; i < *num_args; i++) {
  1092.     X    if (strcmp(args[i].name, XtNinsertBefore) == 0) {
  1093.     X        MenuConstraint mc = (MenuConstraint) w->core.constraints;
  1094.     X        MenuWidget menu = (MenuWidget) XtParent(w);
  1095.     X
  1096.     X        for (j = 0; j < menu->composite.num_children; j++) {
  1097.     X        if (menu->composite.children[j] == w) {
  1098.     X            if (j == menu->composite.num_children - 1) {
  1099.     X            args[i].value = NULL;
  1100.     X            } else {
  1101.     X            *(Widget *) (args[i].value) = 
  1102.     X                menu->composite.children[j+1];
  1103.     X            }
  1104.     X            break;
  1105.     X        }
  1106.     X        } /* End of for loop checking children */
  1107.     X    }
  1108.     X    }
  1109.     X}
  1110. SHAR_EOF
  1111. if test 18170 -ne "`wc -c < 'Menu.c'`"
  1112. then
  1113.     echo shar: error transmitting "'Menu.c'" '(should have been 18170 characters)'
  1114. fi
  1115. fi # end of overwriting check
  1116. echo shar: extracting "'MenuItem.c'" '(3153 characters)'
  1117. if test -f 'MenuItem.c'
  1118. then
  1119.     echo shar: will not over-write existing file "'MenuItem.c'"
  1120. else
  1121. sed 's/^    X//' << \SHAR_EOF > 'MenuItem.c'
  1122.     X/***********************************************************
  1123.     XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  1124.     X
  1125.     X                        All Rights Reserved
  1126.     X
  1127.     XPermission to use, copy, modify, and distribute these examples for any
  1128.     Xpurpose and without fee is hereby granted, provided that the above
  1129.     Xcopyright notice appear in all copies and that both that copyright
  1130.     Xnotice and this permission notice appear in supporting documentation,
  1131.     Xand that the name of Digital not be used in advertising or publicity
  1132.     Xpertaining to distribution of the software without specific, written
  1133.     Xprior permission.
  1134.     X
  1135.     XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  1136.     XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1137.     XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  1138.     XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  1139.     XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1140.     XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  1141.     XOR PERFORMANCE OF THIS SOFTWARE.
  1142.     X
  1143.     X******************************************************************/
  1144.     X
  1145.     X#include <X11/IntrinsicP.h>    /* Intrinsics header file */
  1146.     X#include "MenuItemP.h"        /* MenuItem private header file */
  1147.     X
  1148.     Xstatic char defaultTranslations[] =
  1149.     X    "<EnterWindow>    : invert()        \n\
  1150.     X     <LeaveWindow>    : uninvert()        \n\
  1151.     X     <BtnUp>    : notify() uninvert()";
  1152.     X
  1153.     X/* Class record declaration */
  1154.     X
  1155.     XMenuItemClassRec menuItemClassRec = {
  1156.     X    /* Core class part */
  1157.     X  {
  1158.     X    /* superclass         */    (WidgetClass) &pushbuttonClassRec,
  1159.     X    /* class_name         */    "MenuItem",
  1160.     X    /* widget_size         */    sizeof(MenuItemRec),
  1161.     X    /* class_initialize      */ NULL,
  1162.     X    /* class_part_initialize */    NULL,
  1163.     X    /* class_inited          */    FALSE,
  1164.     X    /* initialize         */    NULL,
  1165.     X    /* initialize_hook       */    NULL,        
  1166.     X    /* realize             */    XtInheritRealize,
  1167.     X    /* actions             */    NULL,
  1168.     X    /* num_actions         */    0,
  1169.     X    /* resources         */    NULL,
  1170.     X    /* num_resources         */    0,
  1171.     X    /* xrm_class         */    NULLQUARK,
  1172.     X    /* compress_motion         */    TRUE,
  1173.     X    /* compress_exposure     */    XtExposeCompressMultiple,
  1174.     X    /* compress_enterleave   */    TRUE,
  1175.     X    /* visible_interest         */    FALSE,
  1176.     X    /* destroy             */    NULL,
  1177.     X    /* resize             */    XtInheritResize,
  1178.     X    /* expose             */    XtInheritExpose,
  1179.     X    /* set_values         */    NULL,
  1180.     X    /* set_values_hook       */    NULL,            
  1181.     X    /* set_values_almost     */    XtInheritSetValuesAlmost,  
  1182.     X    /* get_values_hook       */    NULL,            
  1183.     X    /* accept_focus         */    NULL,
  1184.     X    /* version             */    XtVersion,
  1185.     X    /* callback offsets      */ NULL,
  1186.     X    /* tm_table              */ defaultTranslations,
  1187.     X    /* query_geometry         */    XtInheritQueryGeometry,
  1188.     X    /* display_accelerator   */ XtInheritDisplayAccelerator,
  1189.     X    /* extension             */ NULL
  1190.     X  },
  1191.     X    /* Label class part */
  1192.     X  {
  1193.     X    /* select_text         */ InheritSelectText,
  1194.     X    /* extension             */ NULL
  1195.     X  },
  1196.     X    /* Pushbutton class part */
  1197.     X  {
  1198.     X    /* extension             */ NULL
  1199.     X  },
  1200.     X    /* MenuItem class part */
  1201.     X  {
  1202.     X    /* extension             */ NULL
  1203.     X  }
  1204.     X};
  1205.     X
  1206.     X/* Class record pointer */
  1207.     X
  1208.     XWidgetClass menuItemWidgetClass = (WidgetClass) &menuItemClassRec;
  1209. SHAR_EOF
  1210. if test 3153 -ne "`wc -c < 'MenuItem.c'`"
  1211. then
  1212.     echo shar: error transmitting "'MenuItem.c'" '(should have been 3153 characters)'
  1213. fi
  1214. fi # end of overwriting check
  1215. echo shar: extracting "'MinMax.c'" '(15738 characters)'
  1216. if test -f 'MinMax.c'
  1217. then
  1218.     echo shar: will not over-write existing file "'MinMax.c'"
  1219. else
  1220. sed 's/^    X//' << \SHAR_EOF > 'MinMax.c'
  1221.     X/***********************************************************
  1222.     XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  1223.     X
  1224.     X                        All Rights Reserved
  1225.     X
  1226.     XPermission to use, copy, modify, and distribute these examples for any
  1227.     Xpurpose and without fee is hereby granted, provided that the above
  1228.     Xcopyright notice appear in all copies and that both that copyright
  1229.     Xnotice and this permission notice appear in supporting documentation,
  1230.     Xand that the name of Digital not be used in advertising or publicity
  1231.     Xpertaining to distribution of the software without specific, written
  1232.     Xprior permission.
  1233.     X
  1234.     XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  1235.     XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1236.     XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  1237.     XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  1238.     XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1239.     XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  1240.     XOR PERFORMANCE OF THIS SOFTWARE.
  1241.     X
  1242.     X******************************************************************/
  1243.     X
  1244.     X#include <X11/IntrinsicP.h>    /* Intrinsics header file */
  1245.     X#include <X11/StringDefs.h>    /* Resource string definitions */
  1246.     X#include "MinMaxP.h"        /* MinMax private header file */
  1247.     X#include "LabelGadge.h"        /* To check LabelGadgets */
  1248.     X
  1249.     X#define Offset(field) XtOffsetOf(MinMaxRec, minMax.field)
  1250.     X
  1251.     Xstatic XtResource resources[] = {
  1252.     X    {XtNmargin, XtCMargin, XtRDimension, sizeof(Dimension),
  1253.     X    Offset(margin), XtRImmediate, (XtPointer) 10},
  1254.     X};
  1255.     X
  1256.     X#undef Offset
  1257.     X
  1258.     X#define Offset(field) XtOffsetOf(MinMaxConstraintRec, field)
  1259.     X
  1260.     Xstatic XtResource constraintResources[] = {
  1261.     X    {XtNminWidth, XtCMinWidth, XtRShort, sizeof(short),
  1262.     X        Offset(minMax.min_width), XtRImmediate, (XtPointer) -1},
  1263.     X    {XtNmaxWidth, XtCMaxWidth, XtRShort, sizeof(short),
  1264.     X        Offset(minMax.max_width), XtRImmediate, (XtPointer) -1},
  1265.     X    {XtNminHeight, XtCMinHeight, XtRShort, sizeof(short),
  1266.     X        Offset(minMax.min_height), XtRImmediate, (XtPointer) -1},
  1267.     X    {XtNmaxHeight, XtCMaxHeight, XtRShort, sizeof(short),
  1268.     X        Offset(minMax.max_height), XtRImmediate, (XtPointer) -1},
  1269.     X};
  1270.     X#undef Offset
  1271.     X
  1272.     X/* Forward declarations */
  1273.     X
  1274.     Xstatic void ChangeManaged(), Initialize(), ConstraintInitialize(),
  1275.     X    Resize(), InsertChild(), DeleteChild(), Redisplay();
  1276.     Xstatic XtGeometryResult GeometryManager();
  1277.     Xstatic Boolean SetValues(), AcceptFocus(), ConstraintSetValues();
  1278.     X
  1279.     Xstatic CompositeClassExtensionRec compositeExtension = {
  1280.     X    /* next_extension        */ NULL,
  1281.     X    /* record_type        */ NULLQUARK,
  1282.     X    /* version            */ XtCompositeExtensionVersion,
  1283.     X    /* record_size        */ sizeof(CompositeClassExtensionRec),
  1284.     X    /* accepts_objects        */ TRUE
  1285.     X};
  1286.     X
  1287.     XMinMaxClassRec minMaxClassRec = {
  1288.     X    /* Core class part */
  1289.     X  {
  1290.     X    /* superclass         */    (WidgetClass) &constraintClassRec,
  1291.     X    /* class_name         */ "MinMax",
  1292.     X    /* widget_size         */ sizeof(MinMaxRec),
  1293.     X    /* class_initialize      */ NULL,
  1294.     X    /* class_part_initialize */ NULL,
  1295.     X    /* class_inited          */    FALSE,
  1296.     X    /* initialize         */    Initialize,
  1297.     X    /* initialize_hook       */    NULL,
  1298.     X    /* realize             */    XtInheritRealize,
  1299.     X    /* actions             */    NULL,
  1300.     X    /* num_actions         */    0,
  1301.     X    /* resources         */    resources,
  1302.     X    /* num_resources         */    XtNumber(resources),
  1303.     X    /* xrm_class         */    NULLQUARK,
  1304.     X    /* compress_motion         */    TRUE,
  1305.     X    /* compress_exposure     */    XtExposeCompressMultiple,
  1306.     X    /* compress_enterleave   */    TRUE,
  1307.     X    /* visible_interest         */    FALSE,
  1308.     X    /* destroy             */    NULL,
  1309.     X    /* resize             */    Resize,
  1310.     X    /* expose             */    Redisplay,
  1311.     X    /* set_values         */    SetValues,
  1312.     X    /* set_values_hook       */    NULL,            
  1313.     X    /* set_values_almost     */    XtInheritSetValuesAlmost,  
  1314.     X    /* get_values_hook       */    NULL,            
  1315.     X    /* accept_focus         */    AcceptFocus,
  1316.     X    /* version             */    XtVersion,
  1317.     X    /* callback offsets      */    NULL,
  1318.     X    /* tm_table              */    NULL,
  1319.     X    /* query_geometry         */    XtInheritQueryGeometry,
  1320.     X    /* display_accelerator   */    NULL,
  1321.     X    /* extension         */    NULL,
  1322.     X  },
  1323.     X   /* Composite class part */
  1324.     X  {
  1325.     X    /* geometry_manager         */    GeometryManager,
  1326.     X    /* change_managed         */    ChangeManaged,
  1327.     X    /* insert_child         */    InsertChild,
  1328.     X    /* delete_child         */    DeleteChild,
  1329.     X    /* extension         */    (XtPointer) &compositeExtension,
  1330.     X  },
  1331.     X   /* Constraint class part */
  1332.     X  {
  1333.     X   /* resources             */ constraintResources,
  1334.     X   /* num_resources         */ XtNumber(constraintResources),
  1335.     X   /* constraint_size         */ sizeof(MinMaxConstraintRec),
  1336.     X   /* initialize         */ ConstraintInitialize,
  1337.     X   /* destroy             */ NULL,
  1338.     X   /* set_values         */ ConstraintSetValues,
  1339.     X   /* extension             */ NULL
  1340.     X  },
  1341.     X   /* MinMax class part */
  1342.     X  {
  1343.     X    /* extension         */    NULL,
  1344.     X  }
  1345.     X};
  1346.     X
  1347.     XWidgetClass minMaxWidgetClass = (WidgetClass) &minMaxClassRec;
  1348.     X
  1349.     Xstatic void InsertChild(w)
  1350.     X    Widget w;
  1351.     X{
  1352.     X    String params[2];
  1353.     X    Cardinal num_params;
  1354.     X    Widget parent = XtParent(w);
  1355.     X
  1356.     X    if (!XtIsWidget(w) && !XtIsSubclass(w, labelGadgetClass)) {
  1357.     X    params[0] = XtClass(w)->core_class.class_name;
  1358.     X    params[1] = XtClass(parent)->core_class.class_name;
  1359.     X    num_params = 2;
  1360.     X    XtAppErrorMsg(XtWidgetToApplicationContext(w),
  1361.     X        "childError", "class", "WidgetError",
  1362.     X        "Children of class %s cannot be added to %n widgets",
  1363.     X        params, &num_params);
  1364.     X    }
  1365.     X
  1366.     X    (*((CompositeWidgetClass)(minMaxWidgetClass->
  1367.     X        core_class.superclass))->composite_class.insert_child) (w);
  1368.     X}
  1369.     X
  1370.     Xstatic void DeleteChild(w)
  1371.     X    Widget w;
  1372.     X{
  1373.     X    MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
  1374.     X
  1375.     X    if (minMax->minMax.last_focus == w) {
  1376.     X    minMax->minMax.last_focus = NULL;
  1377.     X    }
  1378.     X
  1379.     X    (*((CompositeWidgetClass)(minMaxWidgetClass->
  1380.     X        core_class.superclass))->composite_class.delete_child) (w);
  1381.     X}
  1382.     X
  1383.     Xstatic void Initialize(req, new, args, num_args)
  1384.     X    Widget req, new;
  1385.     X    ArgList args;
  1386.     X    Cardinal *num_args;
  1387.     X{
  1388.     X    ((MinMaxWidget) new)->minMax.last_focus = NULL;
  1389.     X}
  1390.     X
  1391.     Xstatic void CheckConstraint(w, smaller, larger, which)
  1392.     X    Widget w;
  1393.     X    short *smaller, *larger;
  1394.     X    String which;
  1395.     X{
  1396.     X    String params[3];
  1397.     X    Cardinal num_params;
  1398.     X
  1399.     X    if (*smaller > *larger) {
  1400.     X    params[0] = params[1] = which;
  1401.     X    params[2] = XtName(w);
  1402.     X    num_params = 3;
  1403.     X    XtAppWarningMsg(XtWidgetToApplicationContext(w),
  1404.     X        "constraintError",
  1405.     X        "width", "WidgetError", 
  1406.     X        "Min %s greater than max %s for widget %s",
  1407.     X        params, &num_params);
  1408.     X    *smaller = *larger;
  1409.     X    }
  1410.     X}
  1411.     X
  1412.     Xstatic void ResizeWithinConstraints(w, width, height)
  1413.     X    Widget w;
  1414.     X    Dimension *width, *height;
  1415.     X{
  1416.     X    register MinMaxConstraint mmc =
  1417.     X        (MinMaxConstraint) w->core.constraints;
  1418.     X
  1419.     X    if (*width < mmc->minMax.min_width) {
  1420.     X    *width = mmc->minMax.min_width;
  1421.     X    } else if (*width > mmc->minMax.max_width) {
  1422.     X    *width = mmc->minMax.max_width;
  1423.     X    }
  1424.     X
  1425.     X    if (*height < mmc->minMax.min_height) {
  1426.     X    *height = mmc->minMax.min_height;
  1427.     X    } else if (*height > mmc->minMax.max_height) {
  1428.     X    *height = mmc->minMax.max_height;
  1429.     X    }
  1430.     X}
  1431.     X
  1432.     Xstatic void ConstraintInitialize(req, new, args, num_args)
  1433.     X    Widget req, new;
  1434.     X    ArgList args;
  1435.     X    Cardinal *num_args;
  1436.     X{
  1437.     X    MinMaxConstraint mmc = (MinMaxConstraint) new->core.constraints;
  1438.     X    Dimension width = new->core.width, height = new->core.height;
  1439.     X#define MAXDIM 32768
  1440.     X
  1441.     X    if (mmc->minMax.min_width == -1 && mmc->minMax.max_width == -1) {
  1442.     X    mmc->minMax.min_width = mmc->minMax.max_width = width;
  1443.     X    }
  1444.     X    if (mmc->minMax.min_height == -1 && mmc->minMax.max_height == -1) {
  1445.     X    mmc->minMax.min_height = mmc->minMax.max_height = height;
  1446.     X    }
  1447.     X
  1448.     X    if (mmc->minMax.min_width == -1) mmc->minMax.min_width = 1;
  1449.     X    if (mmc->minMax.max_width == -1) mmc->minMax.max_width = MAXDIM;
  1450.     X    if (mmc->minMax.min_height == -1) mmc->minMax.min_height = 1;
  1451.     X    if (mmc->minMax.max_height == -1) mmc->minMax.max_height = MAXDIM;
  1452.     X
  1453.     X    CheckConstraint(new, &mmc->minMax.min_width,
  1454.     X        &mmc->minMax.max_width, "width");
  1455.     X    CheckConstraint(new, &mmc->minMax.min_height,
  1456.     X        &mmc->minMax.max_height, "height");
  1457.     X    ResizeWithinConstraints(new, &width, &height);
  1458.     X
  1459.     X    if (width != new->core.width || height != new->core.height) {
  1460.     X    XtResizeWidget(new, width, height);
  1461.     X    }
  1462.     X#undef MAXDIM
  1463.     X}
  1464.     X
  1465.     Xstatic void CalculateNewSize(minMax, width, height)
  1466.     X    MinMaxWidget minMax;
  1467.     X    register Dimension *width, *height;
  1468.     X{
  1469.     X    register Widget child;
  1470.     X    register int i;
  1471.     X    int right, bottom;
  1472.     X
  1473.     X    *width = *height = 0;
  1474.     X
  1475.     X    for (i = 0; i < minMax->composite.num_children; i++) {
  1476.     X        child = minMax->composite.children[i];
  1477.     X    if (!XtIsManaged(child)) continue;
  1478.     X    right = child->core.x + child->core.width +
  1479.     X        2 * child->core.border_width;
  1480.     X    bottom = child->core.y + child->core.height +
  1481.     X        2 * child->core.border_width;
  1482.     X    if (right > (int) *width) *width = right;
  1483.     X    if (bottom > (int) *height) *height = bottom;
  1484.     X    }
  1485.     X
  1486.     X    *width += minMax->minMax.margin;
  1487.     X    *height += minMax->minMax.margin;
  1488.     X
  1489.     X    if (*width == 0) *width = 1;
  1490.     X    if (*height == 0) *height = 1;
  1491.     X}
  1492.     X
  1493.     Xstatic void ResizeChildren(minMax, initiator)
  1494.     X    MinMaxWidget minMax;
  1495.     X    Widget initiator;
  1496.     X{
  1497.     X    register Widget child;
  1498.     X    register MinMaxConstraint mmc;
  1499.     X    register int i;
  1500.     X    int right, bottom;
  1501.     X    int new_width, new_height;
  1502.     X    int minMax_right = minMax->core.width - minMax->minMax.margin,
  1503.     X    minMax_bottom = minMax->core.height - minMax->minMax.margin;
  1504.     X
  1505.     X    for (i = 0; i < minMax->composite.num_children; i++) {
  1506.     X        child = minMax->composite.children[i];
  1507.     X    if (!XtIsManaged(child) || child == initiator) continue;
  1508.     X
  1509.     X    mmc = (MinMaxConstraint) child->core.constraints;
  1510.     X    new_width = child->core.width;
  1511.     X    new_height = child->core.height;
  1512.     X
  1513.     X    right = child->core.x + child->core.width +
  1514.     X        2 * child->core.border_width;
  1515.     X    bottom = child->core.y + child->core.height +
  1516.     X        2 * child->core.border_width;
  1517.     X
  1518.     X    if (right > minMax_right &&
  1519.     X        child->core.width > mmc->minMax.min_width) {
  1520.     X        new_width -= right - minMax_right;
  1521.     X        if (new_width < mmc->minMax.min_width) {
  1522.     X        new_width = mmc->minMax.min_width;
  1523.     X        }
  1524.     X    } else if (right < minMax_right &&
  1525.     X        child->core.width < mmc->minMax.max_width) {
  1526.     X        new_width += minMax_right - right;
  1527.     X        if (new_width > mmc->minMax.max_width) {
  1528.     X        new_width = mmc->minMax.max_width;
  1529.     X        }
  1530.     X    }
  1531.     X
  1532.     X    if (bottom > minMax_bottom &&
  1533.     X        child->core.height > mmc->minMax.min_height) {
  1534.     X        new_height -= bottom - minMax_bottom;
  1535.     X        if (new_height < mmc->minMax.min_height) {
  1536.     X        new_height = mmc->minMax.min_height;
  1537.     X        }
  1538.     X    } else if (bottom < minMax_bottom &&
  1539.     X        child->core.height < mmc->minMax.max_height) {
  1540.     X        new_height += minMax_bottom - bottom;
  1541.     X        if (new_height > mmc->minMax.max_height) {
  1542.     X        new_height = mmc->minMax.max_height;
  1543.     X        }
  1544.     X    }
  1545.     X
  1546.     X    XtResizeWidget(child, new_width, new_height,
  1547.     X        child->core.border_width);
  1548.     X    }
  1549.     X}
  1550.     X
  1551.     Xstatic void Resize(w)
  1552.     X    Widget w;
  1553.     X{
  1554.     X    ResizeChildren((MinMaxWidget) w, (Widget) NULL);
  1555.     X}
  1556.     X
  1557.     Xstatic void ChangeManaged(w)
  1558.     X    Widget w;
  1559.     X{
  1560.     X    MinMaxWidget minMax = (MinMaxWidget) w;
  1561.     X    XtWidgetGeometry request;
  1562.     X    XtGeometryResult result;
  1563.     X
  1564.     X    CalculateNewSize(minMax, &request.width, &request.height);
  1565.     X
  1566.     X    if (request.width != minMax->core.width ||
  1567.     X        request.height != minMax->core.height) {
  1568.     X    request.request_mode = CWWidth | CWHeight;
  1569.     X    do {
  1570.     X        result = XtMakeGeometryRequest(w,
  1571.     X            &request, (XtWidgetGeometry *) NULL);
  1572.     X    } while (result == XtGeometryAlmost);
  1573.     X
  1574.     X    if (result == XtGeometryYes) {
  1575.     X        ResizeChildren(minMax, (Widget) NULL);
  1576.     X    }
  1577.     X    }
  1578.     X}
  1579.     X
  1580.     Xstatic XtGeometryResult GeometryManager(w, desired, allowed)
  1581.     X    Widget w;
  1582.     X    XtWidgetGeometry *desired, *allowed;
  1583.     X{
  1584.     X    MinMaxWidget minMax = (MinMaxWidget) XtParent(w);
  1585.     X    MinMaxConstraint mmc = (MinMaxConstraint) w->core.constraints;
  1586.     X    XtWidgetGeometry request;
  1587.     X    XtGeometryResult result;
  1588.     X    Dimension save_width, save_height, save_border_width;
  1589.     X    Position save_x, save_y;
  1590.     X
  1591.     X#define Wants(flag) (desired->request_mode & flag)
  1592.     X#define RestoreGeometry(w) { \
  1593.     X    w->core.x = save_x;        w->core.y = save_y; \
  1594.     X    w->core.width = save_width; w->core.height = save_height; \
  1595.     X    w->core.border_width = save_border_width; }
  1596.     X
  1597.     X    /* If the desired change goes outside the constraints, say no */
  1598.     X
  1599.     X    if ((Wants(CWWidth) && (desired->width < mmc->minMax.min_width ||
  1600.     X            desired->width > mmc->minMax.max_width)) ||
  1601.     X        (Wants(CWHeight) &&
  1602.     X            (desired->height < mmc->minMax.min_height ||
  1603.     X            desired->height > mmc->minMax.max_height))) {
  1604.     X    return XtGeometryNo;
  1605.     X    }
  1606.     X
  1607.     X    /* Figure out how big we would be with this change */
  1608.     X
  1609.     X    save_x = w->core.x;
  1610.     X    save_y = w->core.y;
  1611.     X    save_width = w->core.width;
  1612.     X    save_height = w->core.height;
  1613.     X    save_border_width = w->core.border_width;
  1614.     X    if (Wants(CWX)) w->core.x = desired->x;
  1615.     X    if (Wants(CWY)) w->core.y = desired->y;
  1616.     X    if (Wants(CWWidth)) w->core.width = desired->width;
  1617.     X    if (Wants(CWHeight)) w->core.height = desired->height;
  1618.     X    if (Wants(CWBorderWidth)) {
  1619.     X    w->core.border_width = desired->border_width;
  1620.     X    }
  1621.     X
  1622.     X    CalculateNewSize(minMax, &request.width, &request.height);
  1623.     X
  1624.     X    if (request.width == minMax->core.width && 
  1625.     X        request.height == minMax->core.height) {
  1626.     X    if (Wants(XtCWQueryOnly)) RestoreGeometry(w);
  1627.     X    return XtGeometryYes;
  1628.     X    }
  1629.     X
  1630.     X    /* We need to change size in order to accommodate; see if we can */
  1631.     X
  1632.     X    request.request_mode = CWWidth | CWHeight;
  1633.     X    if (Wants(XtCWQueryOnly)) request.request_mode |= XtCWQueryOnly;
  1634.     X
  1635.     X    result = XtMakeGeometryRequest((Widget) minMax, &request, NULL);
  1636.     X    if (result == XtGeometryAlmost) result = XtGeometryNo;
  1637.     X
  1638.     X    if (result == XtGeometryYes && !Wants(XtCWQueryOnly)) {
  1639.     X    ResizeChildren(minMax, w);
  1640.     X    return XtGeometryYes;
  1641.     X    }
  1642.     X
  1643.     X    /* Undo the saved changes */
  1644.     X
  1645.     X    RestoreGeometry(w);
  1646.     X    return result;
  1647.     X#undef Wants
  1648.     X#undef RestoreGeometry
  1649.     X}
  1650.     X
  1651.     Xstatic Boolean SetValues(old, req, new, args, num_args)
  1652.     X    Widget old, req, new;
  1653.     X    ArgList args;
  1654.     X    Cardinal *num_args;
  1655.     X{
  1656.     X    register MinMaxWidget oldminMax = (MinMaxWidget) old;
  1657.     X    register MinMaxWidget newminMax = (MinMaxWidget) new;
  1658.     X
  1659.     X    if (newminMax->minMax.margin != oldminMax->minMax.margin ||
  1660.     X        newminMax->core.width == 0 ||
  1661.     X        newminMax->core.height == 0) {
  1662.     X    CalculateNewSize(newminMax,
  1663.     X        &newminMax->core.width, &newminMax->core.height);
  1664.     X    }
  1665.     X
  1666.     X    return FALSE;
  1667.     X}
  1668.     X
  1669.     Xstatic Boolean ConstraintSetValues(old, req, new, args, num_args)
  1670.     X    Widget old, req;
  1671.     X    ArgList args;
  1672.     X    Cardinal *num_args;
  1673.     X    register Widget new;
  1674.     X{
  1675.     X    register MinMaxConstraint mmc = 
  1676.     X        (MinMaxConstraint) new->core.constraints;
  1677.     X
  1678.     X    CheckConstraint(new, &mmc->minMax.min_width,
  1679.     X        &mmc->minMax.max_width, "width");
  1680.     X    CheckConstraint(new, &mmc->minMax.min_height,
  1681.     X        &mmc->minMax.max_height, "height");
  1682.     X    ResizeWithinConstraints(new, &new->core.width, &new->core.height);
  1683.     X
  1684.     X    return FALSE;
  1685.     X}
  1686.     X
  1687.     Xstatic Boolean AcceptFocus(w, time)
  1688.     X    Widget w;
  1689.     X    Time *time;
  1690.     X{
  1691.     X    MinMaxWidget minMax = (MinMaxWidget) w;
  1692.     X    register int i;
  1693.     X
  1694.     X    if (minMax->minMax.last_focus != NULL && 
  1695.     X        XtIsManaged(minMax->minMax.last_focus)) {
  1696.     X    if (XtCallAcceptFocus(minMax->minMax.last_focus, time)) {
  1697.     X        return TRUE;
  1698.     X    }
  1699.     X    }
  1700.     X
  1701.     X    for (i = 0; i < minMax->composite.num_children; i++) {
  1702.     X    if (!XtIsManaged(minMax->composite.children[i])) continue;
  1703.     X    if (XtCallAcceptFocus(minMax->composite.children[i], time)) {
  1704.     X        minMax->minMax.last_focus = minMax->composite.children[i];
  1705.     X        return TRUE;
  1706.     X    }
  1707.     X    }
  1708.     X
  1709.     X    minMax->minMax.last_focus = NULL;
  1710.     X    return FALSE;
  1711.     X}
  1712.     X
  1713.     Xstatic void Redisplay(w, event, region)
  1714.     X    Widget w;
  1715.     X    XEvent *event;
  1716.     X    Region region;
  1717.     X{
  1718.     X    CompositeWidget comp = (CompositeWidget) w;
  1719.     X    int i;
  1720.     X    Widget c;        /* child */
  1721.     X
  1722.     X    for (i = 0; i < comp->composite.num_children; i++) {
  1723.     X    c = comp->composite.children[i];
  1724.     X    if (XtIsManaged(c) && XtIsSubclass(c, labelGadgetClass) &&
  1725.     X        XRectInRegion(region, c->core.x, c->core.y,
  1726.     X            c->core.width + 2*c->core.border_width,
  1727.     X            c->core.height + 2*c->core.border_width)
  1728.     X            != RectangleOut) {
  1729.     X        (*(XtClass(c)->core_class.expose))(c, event, region);
  1730.     X        }
  1731.     X    }
  1732.     X}
  1733. SHAR_EOF
  1734. if test 15738 -ne "`wc -c < 'MinMax.c'`"
  1735. then
  1736.     echo shar: error transmitting "'MinMax.c'" '(should have been 15738 characters)'
  1737. fi
  1738. fi # end of overwriting check
  1739. echo shar: extracting "'Pushbutton.c'" '(13083 characters)'
  1740. if test -f 'Pushbutton.c'
  1741. then
  1742.     echo shar: will not over-write existing file "'Pushbutton.c'"
  1743. else
  1744. sed 's/^    X//' << \SHAR_EOF > 'Pushbutton.c'
  1745.     X/***********************************************************
  1746.     XCopyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  1747.     X
  1748.     X                        All Rights Reserved
  1749.     X
  1750.     XPermission to use, copy, modify, and distribute these examples for any
  1751.     Xpurpose and without fee is hereby granted, provided that the above
  1752.     Xcopyright notice appear in all copies and that both that copyright
  1753.     Xnotice and this permission notice appear in supporting documentation,
  1754.     Xand that the name of Digital not be used in advertising or publicity
  1755.     Xpertaining to distribution of the software without specific, written
  1756.     Xprior permission.
  1757.     X
  1758.     XDIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  1759.     XSOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  1760.     XFITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  1761.     XOR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  1762.     XOF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  1763.     XOR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  1764.     XOR PERFORMANCE OF THIS SOFTWARE.
  1765.     X
  1766.     X******************************************************************/
  1767.     X
  1768.     X#include <string.h>        /* Needed for string manipulation */
  1769.     X#include <X11/IntrinsicP.h>    /* Intrinsics header file */
  1770.     X#include <X11/StringDefs.h>    /* Resource string definitions */
  1771.     X#include "PushbuttoP.h"        /* Pushbutton private header file */
  1772.     X
  1773.     Xstatic void InsPixel(), InsPixmap();
  1774.     X
  1775.     X#define Offset(field) XtOffsetOf(PushbuttonRec, pushbutton.field)
  1776.     X
  1777.     Xstatic XtResource resources[] = { 
  1778.     X    {XtNcallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
  1779.     X    Offset(callback), XtRCallback, (XtPointer) NULL},
  1780.     X    {"pri.vate", "Pri.vate", XtRBoolean, sizeof(Boolean),
  1781.     X    Offset(use_insens_pixel), XtRImmediate, (XtPointer) TRUE},
  1782.     X    {XtNinsensitiveForeground, XtCForeground, XtRPixel, sizeof(Pixel),
  1783.     X    Offset(insensitive_foreground),
  1784.     X    XtRCallProc, (XtPointer) InsPixel},
  1785.     X    {XtNinsensitivePixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
  1786.     X    Offset(insensitive_pixmap),
  1787.     X    XtRCallProc, (XtPointer) InsPixmap},
  1788.     X    {XtNhighlightBorder, XtCBorderWidth,
  1789.     X    XtRDimension, sizeof(Dimension),
  1790.     X    Offset(highlight_border), XtRImmediate, (XtPointer) 1},
  1791.     X    {XtNaccelString, XtCAccelString, XtRString, sizeof(String),
  1792.     X    XtOffsetOf(PushbuttonRec, label.accel_string),
  1793.     X    XtRString, NULL},
  1794.     X    {XtNacceleratorString, XtCAcceleratorString,
  1795.     X    XtRString, sizeof(String),
  1796.     X    Offset(accelerator_string), XtRString, NULL},
  1797.     X    {XtNborderWidth, XtCBorderWidth,
  1798.     X    XtRDimension, sizeof(Dimension),
  1799.     X    XtOffsetOf(PushbuttonRec, core.border_width),
  1800.     X    XtRImmediate, (XtPointer) 1},
  1801.     X};  
  1802.     X
  1803.     X#undef Offset
  1804.     X
  1805.     Xstatic void InsPixel(w, offset, value)
  1806.     X    Widget w;
  1807.     X    int offset;        /* Not used */
  1808.     X    XrmValue *value;
  1809.     X{
  1810.     X    PushbuttonWidget p = (PushbuttonWidget) w;
  1811.     X
  1812.     X    /* Any value will work; it won't be used */
  1813.     X    value->addr = (caddr_t) &p->label.foreground;
  1814.     X    p->pushbutton.use_insens_pixel = FALSE;
  1815.     X}
  1816.     X
  1817.     X/* Return a 2x2 pixmap with the foreground at 50% */
  1818.     X
  1819.     Xstatic Pixmap GetPixmap(pw)
  1820.     X    PushbuttonWidget pw;
  1821.     X{
  1822.     X    static char bits[] = {0x01, 0x02};
  1823.     X
  1824.     X    return XCreatePixmapFromBitmapData(XtDisplay(pw),
  1825.     X        RootWindowOfScreen(XtScreen(pw)), bits, 2, 2,
  1826.     X        pw->label.foreground, pw->core.background_pixel,
  1827.     X        pw->core.depth);
  1828.     X}
  1829.     X
  1830.     Xstatic void InsPixmap(w, offset, value)
  1831.     X    Widget w;
  1832.     X    int offset;        /* Not used */
  1833.     X    XrmValue *value;
  1834.     X{
  1835.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1836.     X    static Pixmap pixmap;
  1837.     X
  1838.     X    if (pw->pushbutton.use_insens_pixel) pixmap = None;
  1839.     X    else pixmap = GetPixmap(pw);
  1840.     X
  1841.     X    value->addr = (caddr_t) &pixmap;
  1842.     X}
  1843.     X
  1844.     Xstatic char defaultTranslations[] =
  1845.     X    "<EnterWindow>    : highlight()        \n\
  1846.     X     <LeaveWindow>    : unhighlight()        \n\
  1847.     X     <Btn1Down>    : invert()        \n\
  1848.     X     <Btn1Up>    : notify() uninvert()";
  1849.     X
  1850.     Xstatic void Highlight(), Unhighlight(), Invert(), Uninvert(), Notify();
  1851.     X
  1852.     Xstatic XtActionsRec actions[] = {
  1853.     X  {"highlight",        Highlight},
  1854.     X  {"unhighlight",    Unhighlight},
  1855.     X  {"invert",        Invert},
  1856.     X  {"uninvert",        Uninvert},
  1857.     X  {"notify",        Notify},
  1858.     X};
  1859.     X
  1860.     X/* Forward declarations */
  1861.     X
  1862.     Xstatic void Initialize(), DisplayAccelerator(), Destroy(), Redisplay();
  1863.     Xstatic Boolean SetValues();
  1864.     X
  1865.     X/* Class record declaration */
  1866.     X
  1867.     XPushbuttonClassRec pushbuttonClassRec = {
  1868.     X    /* Core class part */
  1869.     X  {
  1870.     X    /* superclass         */    (WidgetClass) &labelClassRec,
  1871.     X    /* class_name         */    "Pushbutton",
  1872.     X    /* widget_size         */    sizeof(PushbuttonRec),
  1873.     X    /* class_initialize      */ NULL,
  1874.     X    /* class_part_initialize */    NULL,
  1875.     X    /* class_inited          */    FALSE,
  1876.     X    /* initialize         */    Initialize,
  1877.     X    /* initialize_hook       */    NULL,        
  1878.     X    /* realize             */    XtInheritRealize,
  1879.     X    /* actions             */    actions,
  1880.     X    /* num_actions         */    XtNumber(actions),
  1881.     X    /* resources         */    resources,
  1882.     X    /* num_resources         */    XtNumber(resources),
  1883.     X    /* xrm_class         */    NULLQUARK,
  1884.     X    /* compress_motion         */    TRUE,
  1885.     X    /* compress_exposure     */    XtExposeCompressMultiple,
  1886.     X    /* compress_enterleave   */    TRUE,
  1887.     X    /* visible_interest         */    FALSE,
  1888.     X    /* destroy             */    NULL,
  1889.     X    /* resize             */    XtInheritResize,
  1890.     X    /* expose             */    Redisplay,
  1891.     X    /* set_values         */    SetValues,
  1892.     X    /* set_values_hook       */    NULL,            
  1893.     X    /* set_values_almost     */    XtInheritSetValuesAlmost,  
  1894.     X    /* get_values_hook       */    NULL,            
  1895.     X    /* accept_focus         */    NULL,
  1896.     X    /* version             */    XtVersion,
  1897.     X    /* callback offsets      */ NULL,
  1898.     X    /* tm_table              */ defaultTranslations,
  1899.     X    /* query_geometry         */    XtInheritQueryGeometry,
  1900.     X    /* display_accelerator   */ DisplayAccelerator,
  1901.     X    /* extension             */ NULL
  1902.     X  },
  1903.     X    /* Label class part */
  1904.     X  {
  1905.     X    /* select_text         */ InheritSelectText,
  1906.     X    /* extension             */ NULL
  1907.     X  },
  1908.     X    /* Pushbutton class part */
  1909.     X  {
  1910.     X    /* extension             */ NULL
  1911.     X  }
  1912.     X};
  1913.     X
  1914.     X/* Class record pointer */
  1915.     X
  1916.     XWidgetClass pushbuttonWidgetClass = (WidgetClass) &pushbuttonClassRec;
  1917.     X
  1918.     Xstatic void Highlight(w, event, params, num_params)
  1919.     X    Widget w;
  1920.     X    XEvent *event;
  1921.     X    String *params;
  1922.     X    Cardinal *num_params;
  1923.     X{
  1924.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1925.     X
  1926.     X    if (!pw->pushbutton.highlighted) {
  1927.     X    pw->pushbutton.highlighted = TRUE;
  1928.     X    if (XtIsRealized(w)) {
  1929.     X        XClearWindow(XtDisplay(w), XtWindow(w));
  1930.     X        (*(XtClass(w)->core_class.expose))(w, event, NULL);
  1931.     X    }
  1932.     X    }
  1933.     X}
  1934.     X
  1935.     Xstatic void Unhighlight(w, event, params, num_params)
  1936.     X    Widget w;
  1937.     X    XEvent *event;
  1938.     X    String *params;
  1939.     X    Cardinal *num_params;
  1940.     X{
  1941.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1942.     X
  1943.     X    if (pw->pushbutton.highlighted) {
  1944.     X    pw->pushbutton.highlighted = FALSE;
  1945.     X    if (XtIsRealized(w)) {
  1946.     X        XClearWindow(XtDisplay(w), XtWindow(w));
  1947.     X        (*(XtClass(w)->core_class.expose))(w, event, NULL);
  1948.     X    }
  1949.     X    }
  1950.     X}
  1951.     X
  1952.     Xstatic void Invert(w, event, params, num_params)
  1953.     X    Widget w;
  1954.     X    XEvent *event;
  1955.     X    String *params;
  1956.     X    Cardinal *num_params;
  1957.     X{
  1958.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1959.     X
  1960.     X    if (!pw->pushbutton.inverted) {
  1961.     X    pw->pushbutton.inverted = TRUE;
  1962.     X    pw->label.current_gc = pw->pushbutton.inverted_gc;
  1963.     X    if (XtIsRealized(w)) {
  1964.     X        XClearWindow(XtDisplay(w), XtWindow(w));
  1965.     X        (*(XtClass(w)->core_class.expose))(w, event, NULL);
  1966.     X    }
  1967.     X    }
  1968.     X}
  1969.     X
  1970.     Xstatic void Uninvert(w, event, params, num_params)
  1971.     X    Widget w;
  1972.     X    XEvent *event;
  1973.     X    String *params;
  1974.     X    Cardinal *num_params;
  1975.     X{
  1976.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1977.     X
  1978.     X    if (pw->pushbutton.inverted) {
  1979.     X    pw->pushbutton.inverted = FALSE;
  1980.     X    if (XtIsSensitive(w)) {
  1981.     X        pw->label.current_gc = pw->label.gc;
  1982.     X    } else pw->label.current_gc = pw->pushbutton.insensitive_gc;
  1983.     X
  1984.     X    if (XtIsRealized(w)) {
  1985.     X        XClearWindow(XtDisplay(w), XtWindow(w));
  1986.     X        (*(XtClass(w)->core_class.expose))(w, event, NULL);
  1987.     X    }
  1988.     X    }
  1989.     X}
  1990.     X
  1991.     Xstatic void Notify(w, event, params, num_params)
  1992.     X    Widget w;
  1993.     X    XEvent *event;
  1994.     X    String *params;
  1995.     X    Cardinal *num_params;
  1996.     X{
  1997.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  1998.     X
  1999.     X    /* If event is a button event, and the event's window is the
  2000.     X       widget's window, we were invoked normally.  Make sure
  2001.     X       the pointer is really in the window */
  2002.     X
  2003.     X    if (event != NULL && event->type == ButtonRelease &&
  2004.     X        event->xany.window == XtWindow(w)) {
  2005.     X    XButtonEvent *b = &event->xbutton;
  2006.     X    if (b->x < 0 || b->y < 0 ||
  2007.     X        b->x >= w->core.width || b->y >= w->core.height) return;
  2008.     X    }
  2009.     X
  2010.     X    XtCallCallbackList(pw, pw->pushbutton.callback, NULL);
  2011.     X}
  2012.     X
  2013.     Xstatic GC GetInvertedGC(pw)
  2014.     X    PushbuttonWidget pw;
  2015.     X{
  2016.     X    XGCValues    values;
  2017.     X
  2018.     X    values.foreground = pw->core.background_pixel;
  2019.     X    values.font = pw->label.font->fid;
  2020.     X    return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
  2021.     X}
  2022.     X
  2023.     Xstatic GC GetInsensitiveGC(pw)
  2024.     X    PushbuttonWidget pw;
  2025.     X{
  2026.     X    XGCValues    values;
  2027.     X
  2028.     X    values.font = pw->label.font->fid;
  2029.     X
  2030.     X    if (pw->pushbutton.use_insens_pixel) {
  2031.     X    values.foreground = pw->pushbutton.insensitive_foreground;
  2032.     X    return XtGetGC((Widget) pw, GCForeground | GCFont, &values);
  2033.     X    } else {
  2034.     X    values.tile = pw->pushbutton.insensitive_pixmap;
  2035.     X    values.fill_style = FillTiled;
  2036.     X    return XtGetGC((Widget) pw,
  2037.     X        GCTile | GCFont | GCFillStyle, &values);
  2038.     X    }
  2039.     X}
  2040.     X
  2041.     Xstatic void Initialize(req, new)
  2042.     X    Widget req, new;
  2043.     X{
  2044.     X    PushbuttonWidget pw = (PushbuttonWidget) new;
  2045.     X
  2046.     X    pw->pushbutton.insensitive_gc = GetInsensitiveGC(pw);
  2047.     X    pw->pushbutton.inverted_gc = GetInvertedGC(pw);
  2048.     X    pw->pushbutton.accelerator_string =
  2049.     X        XtNewString(pw->pushbutton.accelerator_string);
  2050.     X
  2051.     X    pw->pushbutton.highlighted = pw->pushbutton.inverted = FALSE;
  2052.     X
  2053.     X    if (!XtIsSensitive(pw)) {
  2054.     X    pw->label.current_gc = pw->pushbutton.insensitive_gc;
  2055.     X    }
  2056.     X}
  2057.     X
  2058.     Xstatic Boolean SetValues(old, req, new, args, num_args)
  2059.     X    Widget  old, req, new;
  2060.     X    ArgList args;
  2061.     X    Cardinal *num_args;
  2062.     X{
  2063.     X    PushbuttonWidget oldpw = (PushbuttonWidget) old;
  2064.     X    PushbuttonWidget newpw = (PushbuttonWidget) new;
  2065.     X
  2066.     X#define NE(field) (oldpw->field != newpw->field)
  2067.     X
  2068.     X    /* If insensitive fields or button's font has changed, 
  2069.     X       update insensitive GC */
  2070.     X
  2071.     X    if (NE(pushbutton.insensitive_foreground)) {
  2072.     X    newpw->pushbutton.use_insens_pixel = TRUE;
  2073.     X    }
  2074.     X
  2075.     X    if (NE(pushbutton.insensitive_pixmap)) {
  2076.     X    if (newpw->pushbutton.insensitive_pixmap == None) {
  2077.     X        newpw->pushbutton.insensitive_pixmap = GetPixmap(newpw);
  2078.     X    }
  2079.     X        newpw->pushbutton.use_insens_pixel = FALSE;
  2080.     X    }
  2081.     X
  2082.     X    if (NE(pushbutton.insensitive_foreground) || 
  2083.     X        NE(pushbutton.insensitive_pixmap) || NE(label.font->fid)) {
  2084.     X    XtReleaseGC(newpw, oldpw->pushbutton.insensitive_gc);
  2085.     X    newpw->pushbutton.insensitive_gc = GetInsensitiveGC(newpw);
  2086.     X
  2087.     X    if (newpw->label.current_gc ==
  2088.     X        oldpw->pushbutton.insensitive_gc) {
  2089.     X        newpw->label.current_gc = newpw->pushbutton.insensitive_gc;
  2090.     X    }
  2091.     X    }
  2092.     X
  2093.     X    /* If background or font has changed, update inverted GC */
  2094.     X
  2095.     X    if (NE(core.background_pixel) || NE(label.font->fid)) {
  2096.     X    XtReleaseGC(newpw, oldpw->pushbutton.inverted_gc);
  2097.     X    newpw->pushbutton.inverted_gc = GetInvertedGC(newpw);
  2098.     X
  2099.     X    if (newpw->pushbutton.inverted) {
  2100.     X        newpw->label.current_gc = newpw->pushbutton.inverted_gc;
  2101.     X    }
  2102.     X    }
  2103.     X
  2104.     X    /* If sensitivity changing, adjust appearance */
  2105.     X
  2106.     X    if (NE(core.sensitive) || NE(core.ancestor_sensitive)) {
  2107.     X    if (XtIsSensitive(newpw)) {    /* Just made sensitive */
  2108.     X        newpw->label.current_gc = newpw->label.gc;
  2109.     X
  2110.     X    } else {            /* Just made insensitive */
  2111.     X        newpw->label.current_gc = 
  2112.     X            newpw->pushbutton.insensitive_gc;
  2113.     X
  2114.     X        /* If currently highlighted, will never receive
  2115.     X           leave event to unhighlight, so unhighlight */
  2116.     X        newpw->pushbutton.highlighted = FALSE;
  2117.     X    }
  2118.     X    }
  2119.     X
  2120.     X    /* If current graphics context has changed, inverted
  2121.     X       and foreground has changed, or highlighted and highlight
  2122.     X       width has changed, redisplay */
  2123.     X
  2124.     X    return NE(label.current_gc) ||
  2125.     X       (NE(label.foreground) && newpw->pushbutton.inverted) ||
  2126.     X       (NE(pushbutton.highlight_border) &&
  2127.     X           newpw->pushbutton.highlighted);
  2128.     X#undef NE
  2129.     X}
  2130.     X
  2131.     Xstatic void Destroy(w)
  2132.     X    Widget w;
  2133.     X{
  2134.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  2135.     X
  2136.     X    /* Release the GCs */
  2137.     X
  2138.     X    XtReleaseGC(w, pw->pushbutton.insensitive_gc);
  2139.     X    XtReleaseGC(w, pw->pushbutton.inverted_gc);
  2140.     X
  2141.     X    XtFree(pw->pushbutton.accelerator_string);
  2142.     X    XtFree(pw->label.accel_string);
  2143.     X}
  2144.     X
  2145.     Xstatic void Redisplay(w, event, region)
  2146.     X    Widget w;
  2147.     X    XEvent *event;
  2148.     X    Region region;
  2149.     X{
  2150.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  2151.     X    int offset;
  2152.     X
  2153.     X    /* If inverted, fill background with the foreground color */
  2154.     X
  2155.     X    if (pw->pushbutton.inverted) {
  2156.     X    XFillRectangle(XtDisplay(w), XtWindow(w), pw->label.gc,
  2157.     X        0, 0, pw->core.width, pw->core.height);
  2158.     X    }
  2159.     X
  2160.     X    /* If highlighted, draw highlighting border */
  2161.     X
  2162.     X    if (pw->pushbutton.highlighted) {
  2163.     X    offset = pw->pushbutton.highlight_border / 2;
  2164.     X    XDrawRectangle(XtDisplay(w), XtWindow(w), pw->label.current_gc,
  2165.     X        offset, offset,
  2166.     X        pw->core.width - pw->pushbutton.highlight_border,
  2167.     X        pw->core.height - pw->pushbutton.highlight_border);
  2168.     X    }
  2169.     X
  2170.     X    /* Make Label redisplay the string */
  2171.     X
  2172.     X    (*pushbuttonWidgetClass->core_class.superclass->core_class.expose)
  2173.     X        (w, event, region);
  2174.     X}
  2175.     X
  2176.     Xstatic void DisplayAccelerator(w, string)
  2177.     X    Widget w;
  2178.     X    String string;
  2179.     X{
  2180.     X    PushbuttonWidget pw = (PushbuttonWidget) w;
  2181.     X    Arg args[1];
  2182.     X
  2183.     X    if (pw->pushbutton.accelerator_string != NULL) {
  2184.     X    XtSetArg(args[0], XtNaccelString,
  2185.     X        pw->pushbutton.accelerator_string);
  2186.     X    XtSetValues(w, args, 1);
  2187.     X    }
  2188.     X}
  2189. SHAR_EOF
  2190. if test 13083 -ne "`wc -c < 'Pushbutton.c'`"
  2191. then
  2192.     echo shar: error transmitting "'Pushbutton.c'" '(should have been 13083 characters)'
  2193. fi
  2194. fi # end of overwriting check
  2195. #    End of shell archive
  2196. exit 0
  2197.  
  2198. dan
  2199. ----------------------------------------------------
  2200. O'Reilly && Associates   argv@sun.com / argv@ora.com
  2201. Opinions expressed reflect those of the author only.
  2202.